#include "gt_line.h"
#include "gt_entry.h"
#include "gt_theme.h"

// ok
static void *get_line(entry_t *entry, entry_type_t type) {
  if (type == LINE_ENTRY)
    return container_of(entry, line_t, entry);

  return NULL;
}

// ok
entry_vtable line_vtable = {display_line, is_line_selectable, free_line,
                            get_line};

// ok
entry_t *create_line(result_t *result, char *line, int line_number,
                     range_t match) {
  int len = strlen(line) + 1;
  line_t *new_line;

  new_line = (line_t *)calloc(1, sizeof(line_t) + len);

  strncpy(new_line->entry.data, line, len);
  new_line->opened = 0;
  new_line->is_selectable = 1;
  new_line->line = line_number;
  new_line->highlight.begin = match.begin;
  new_line->highlight.end = match.end;
  result->nbentry++;

  new_line->entry.vtable = &line_vtable;

  if (result->entries)
    result->entries->next = &new_line->entry;
  else
    result->start = &new_line->entry;

  return &new_line->entry;
}

// ok
entry_t *create_unselectable_line(result_t *result, char *line,
                                  int line_number) {
  range_t no_match = {0, 0};
  entry_t *entry = create_line(result, line, line_number, no_match);
  line_t *new_line = container_of(entry, line_t, entry);

  new_line->is_selectable = 0;

  return entry;
}

// ok
entry_t *create_blank_line(result_t *result) {
  return create_unselectable_line(result, "", 0);
}

// ok
static int get_integer_as_string(int integer, char *out_string) {
  sprintf(out_string, "%d", integer);
  return strlen(out_string) + 1;
}

// ok
static void hilight_pattern(line_t *container, char *line, int y) {
  char *ptr = (char *)line;
  char buffer[32];
  int length = get_integer_as_string(container->line, buffer);

  move(y, length);

  while (container->highlight.begin > (ptr - line)) {
    addch(*ptr);
    ptr++;
  }

  attron(A_REVERSE);

  if (container->opened)
    attron(COLOR_PAIR(COLOR_OPENED_LINE));
  else
    attron(COLOR_PAIR(COLOR_HIGHLIGHT));

  length = container->highlight.end - container->highlight.begin;
  int counter;
  for (counter = 0; counter < length; counter++, ptr++)
    addch(*ptr);

  attroff(A_REVERSE);
}

// ok
void display_line(entry_t *entry, search_t *search, int y,
                  int is_cursor_on_entry) {
  int length = 0;
  char cropped_line[PATH_MAX] = "";
  char *line = entry->data;
  if (is_cursor_on_entry)
    attron(A_REVERSE);

  move(y, 0);
  clrtoeol();

  line_t *container = container_of(entry, line_t, entry);

  if (container->line == 0) {
    for (int i = 0; i < COLS; ++i)
      cropped_line[i] = '-';

    attron(A_BOLD);
    attron(COLOR_PAIR(COLOR_FILE));
    mvprintw(y, 0, "%s", cropped_line);
    attroff(COLOR_PAIR(COLOR_FILE));
    attroff(A_BOLD);
    return;
  }

  attron(COLOR_PAIR(COLOR_LINE_NUMBER));
  mvprintw(y, 0, "%d:", container->line);

  char line_begin[16];
  sprintf(line_begin, "%d", container->line);
  length = strlen(line_begin) + 1;
  attron(COLOR_PAIR(COLOR_LINE));
  strncpy(cropped_line, line, COLS - length);
  mvprintw(y, length, "%s", cropped_line);

  hilight_pattern(container, cropped_line, y);
  if (is_cursor_on_entry)
    attroff(A_REVERSE);
}

// ok
int is_line_selectable(entry_t *entry) {
  line_t *line = container_of(entry, line_t, entry);

  return line->is_selectable;
}

// ok
void free_line(entry_t *entry) {
  line_t *ptr = container_of(entry, line_t, entry);
  free(ptr);
}